
package com.xkw.autocode.logaspect;

import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.ValueFilter;
import com.xkw.autocode.base.BaseController;
import com.xkw.autocode.util.HttpContextUtils;
import com.xkw.autocode.util.IpUtils;
import com.xkw.autocode.vo.SystemLogsVo;
import com.xkw.autocode.vo.UserConfigVo;
import com.xkw.autocode.web.systemlogs.ao.SystemLogsAo;

/**
 * 系统日志，切面处理类
 *
 */
@Aspect
@Component
public class SystemLogsAspect {

	private static Logger logger = LoggerFactory.getLogger(SystemLogsAspect.class);

	private static final char D = '.';
	@Autowired
	private SystemLogsAo systemLogsAo;

	private static Map<String, String> filterParamSet;
	static {
		filterParamSet = new HashMap<>();
		filterParamSet.put("pwdvalue", "...");
		filterParamSet.put("templateContent", "...");
	}

	@Pointcut("@annotation(com.xkw.autocode.logaspect.SysLog)")
	public void logPointCut() {
		//
	}

	@Around("logPointCut()")
	public Object around(ProceedingJoinPoint point) throws Throwable {
		long beginTime = System.currentTimeMillis();

		// 执行方法
		Object result = point.proceed();

		// 执行时长(毫秒)
		long time = System.currentTimeMillis() - beginTime;

		// 保存日志
		saveSysLog(point, time);

		return result;
	}

	private void saveSysLog(ProceedingJoinPoint joinPoint, long time) {
		MethodSignature signature = (MethodSignature) joinPoint.getSignature();
		Method method = signature.getMethod();

		SystemLogsVo sysLog = new SystemLogsVo();
		SysLog syslog = method.getAnnotation(SysLog.class);
		if (syslog != null) {
			StringBuilder operation = new StringBuilder();

			String option = syslog.option();
			if (StringUtils.isNotEmpty(option)) {
				operation.append("[" + option + "]");
			}
			operation.append(syslog.value());

			// 注解上的描述
			sysLog.setOperation(operation.toString());
		}

		// 获取request
		HttpServletRequest request = HttpContextUtils.getHttpServletRequest();

		sysLog.setMethod(this.getUri(request) + "\n"
				+ this.getMethod(joinPoint.getTarget().getClass().getName(), signature.getName()));

		// 请求的参数
		try {
			sysLog.setParams(this.getParams(signature.getParameterNames(), joinPoint.getArgs()));
		} catch (Exception e) {
			logger.error("", e);
		}

		// 设置IP地址
		sysLog.setIp(IpUtils.getIpAddr(request));

		// 用户名
		UserConfigVo user = (UserConfigVo) request.getSession().getAttribute(BaseController.SESSION_USER_KEY);
		if (user != null) {
			sysLog.setUserName(user.getUserName());
			sysLog.setUserId(user.getId());
		}

		sysLog.setOpTime(time);

		// 保存系统日志
		systemLogsAo.insertSystemLogs(sysLog);
	}

	private String getMethod(String className, String methodName) {
		// 请求的方法名
		if (className.indexOf(D) != -1) {
			className = className.substring(className.lastIndexOf(D) + 1);
		}
		return className + D + methodName + "()";
	}

	private String getUri(HttpServletRequest request) {
		String uri = request.getRequestURI();

		String contextPath = request.getContextPath();

		return uri.replace(contextPath, "");
	}

	private String getParams(String[] paramNames,Object[] objects) {

		if (objects == null || objects.length == 0) {
			return "";
		}

		Map<String,Object> paramsMap = new HashMap<>();
		
		for (int  i = 0;i<objects.length ;i++) {
			String paramName = "";
			if(paramNames.length > i) {
				paramName = paramNames[i];
			}
			
			Object obj = objects[i];
			if (obj instanceof HttpServletRequest || obj instanceof HttpServletResponse) {
				continue;
			}
			paramsMap.put(paramName,obj);
		}
		
		return JSON.toJSONString(paramsMap,new MyValueFilter(filterParamSet));

	}
}


class MyValueFilter implements ValueFilter{
	
	private  Map<String, String> filterParamSet;
	
	public MyValueFilter(Map<String, String> filterParamSet) {
		super();
		this.filterParamSet = filterParamSet;
	}

	@Override
    public Object process(Object object, String name, Object value) {
		if(value == null) {
			return "";
		}
		
        if(filterParamSet.containsKey(name)) {
        	return filterParamSet.get(name);
		}
        return value;
    }
}